﻿using MediatR;
using Microsoft.Extensions.Logging;
using NuGet.Packaging;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using QuickGet.Core.Models;
using QuickGet.Core.Stores;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QuickGet.Core
{
    public record InstallPackageCommand(
        string PackageId,
        string PackageVersion,
        string PackageSourceName)
    {
        
    }

    public class InstallPackageHandler
    {
        protected virtual NuGet.Common.ILogger NugetLogger { get; set; }

        protected virtual IPackageStore PackageStore { get; set; }
        protected virtual ILogger Logger { get; set; }
        public virtual CancellationToken CancellationToken => OperationCancellation?.Token ?? CancellationToken.None;
        protected virtual IOperationCancellation? OperationCancellation { get; set; }
        protected virtual NugetResources NugetResources { get; set; }
        protected virtual IPackageSourceStore PackageSourceStore { get; set; }
        protected virtual SourceCacheContext SourceCache { get; set; }

        public InstallPackageHandler(
            IPackageStore packageStore,
            NuGet.Common.ILogger nugetLogger,
            ILogger<InstallPackageHandler> logger,
            NugetResources nugetResources,
            IPackageSourceStore packageSourceStore,
            SourceCacheContext sourceCache,
            IOperationCancellation? cancellation = null)
        {
            PackageStore = packageStore;
            Logger = logger;
            NugetLogger = nugetLogger;
            OperationCancellation = cancellation;
            NugetResources = nugetResources;
            PackageSourceStore = packageSourceStore;
            SourceCache = sourceCache;
        }

        public async Task Execute(InstallPackageCommand command, CancellationToken cancellationToken)
        {
            var resource = await NugetResources.GetFindPackageByIdResourceAsync(command.PackageSourceName, CancellationToken);

            if (resource is null)
            {
                var packageSource = await PackageSourceStore.GetAsync(command.PackageSourceName, CancellationToken);
                if (packageSource is null)
                {
                    Logger.LogWarning("Package Source '{PackageSourceName}' is not configured", command.PackageSourceName);

                    return;
                }

                resource = await NugetResources.GetFindPackageByIdResourceAsync(packageSource, CancellationToken);
            }

            if (resource is null)
            {
                return;
            }

            var packageVersion = new NuGetVersion(command.PackageVersion);

            using var ms = new MemoryStream();

            await resource.CopyNupkgToStreamAsync(
                command.PackageId,
                packageVersion,
                ms,
                SourceCache,
                NugetLogger,
                CancellationToken);

            Logger.LogDebug("Downloaded package: {PackageId} {PackageVersion}", command.PackageId, command.PackageVersion);

            using var packageReader = new PackageArchiveReader(ms);

            var nuspecReader = await packageReader.GetNuspecReaderAsync(CancellationToken);
        }
    }
}
